package gbench.appdemo.myworld.market.trading;

import java.util.Map;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

import gbench.appdemo.myworld.market.SimpleMarket;
import gbench.appdemo.myworld.market.SimpleMarket.DRCR;
import gbench.appdemo.myworld.market.commodity.Commodity;
import gbench.appdemo.myworld.market.license.CommodityLicense;
import gbench.appdemo.myworld.market.license.CommodityLicenseGroup;
import gbench.common.tree.LittleTree.IRecord;

/**
 * TradeProxy 是对 商品与OnlineStore 关系的管理。
 * 交易角色代理：就像一个证券经纪人一样的工作,一个TradeProxy 就是一个拥有多个CommodityLicense的对象。
 * @author gbench
 *
 */
public class TradeProxy<SELF>{

    /**
     * 交易许可
     * @param currentParticipant 当前交易者
     * @param licenses 交易许可
     */
    public TradeProxy(final String currentParticipant, final Map<String,CommodityLicense<Commodity,Commodity>> licenses) {
        this.currentParticipant = currentParticipant;
        this.licenses = licenses;
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量
     * @param ta 换出的对象
     * @param na 换出的数量
     */
    public void debitB(final String partB,final Commodity ub, final Number nb, final Commodity ta, final Number na) {
       this.getCurrent().commitTransaction(DRCR.CR, ta, na, this.getLicense(partB), ub, nb);
    }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量
     * @param ta 换出的对象
     * @param na 换出的数量
     */
    public void debitA(final String partB,final Commodity ta, final Number na,final Commodity ub, final Number nb) {
        this.getCurrent().commitTransaction(DRCR.DR, ta, na, this.getLicense(partB), ub, nb);
     }
    
    /**
     * 使用 (ta,na) - > 换取得 (ub,nb)
     * @param <U> 还如的对象类型
     * @param partB  (ub,nb) 来源 换取方式
     * @param ub 换入的对象
     * @param nb 还如的数量 <br>
     * @param ta 换出的对象 换入对象默认为 TradeRole的 primaryCommodity 
     * @param na 换出的数量
     */
    public <U extends Commodity> void work(String partB,Number nb,Number na) {
       this.getCurrent().debitB(this.getLicense(partB), null,nb,null,na);
    }
    
    /**
     * 
     * @param <U>
     * @param partB
     * @param ub
     * @param nb
     * @param ta
     * @param na
     */
    public void purchase(String partB,Commodity ub,Number nb,Commodity ta,Number na) {
        this.getCurrent().purchase(licenses.get(partB), ub,nb,ta,na);
    }
    
    /**
     * 
     * @param <U>
     * @param partB
     * @param nb
     * @param na
     */
    public <U extends Commodity> void purchase(String partB,Number nb,Number na) {
        this.getCurrent().purchase(licenses.get(partB), nb, na);
    }
    
    /**
     * 试算平衡
     * @return [{name,subject,amount}]
     */
    public Stream<IRecord> trialBalance(){
        return this.trialBalance(null);
    }
    
    /**
     * 试算平衡
     * @param predicate 结果筛选器
     * @return [{name,subject,amount}]
     */
    public Stream<IRecord> trialBalance(Predicate<IRecord> predicate){
        return this.getLicenseGroup().trialBalance(predicate);
    }
    
    /**
     * 复式结账分录
     * @return
     */
    public Stream<IRecord> getDoubleEntries(){
        return this.getLicenseGroup().getDoubleEntries();
    }
    
    /**
     * 获取 复式记账方法
     * @param supplier
     * @return IRecord 的流
     */
    public Stream<IRecord> getDoubleEntries(Supplier<Stream<SimpleMarket<Commodity>.TradeTransaction<Commodity, Commodity>>> supplier){
        return this.getLicenseGroup().getDoubleEntries(supplier);
    }
    
    public Map<String, CommodityLicense<Commodity, Commodity>> getLicenses() {
        return licenses;
    }

    public void setLicenses(Map<String, CommodityLicense<Commodity, Commodity>> licenses) {
        this.licenses = licenses;
    }
    
    /**
     * 
     * @return
     */
    public CommodityLicense<Commodity,Commodity> getCurrent() {
        return this.licenses.get(currentParticipant);
    }
    
    /**
     * 
     * @param name
     * @return
     */
    public CommodityLicense<Commodity,Commodity> getLicense(String name ) {
        return this.licenses.get(currentParticipant);
    }
    
    /**
     * 设置但议案角色名
     * @return TradeRole
     */
    public SELF setCurrent(String name) {
        final var role = this.licenses.get(name);
        if(role!=null) {
            this.currentParticipant = name;
        }
        @SuppressWarnings("unchecked")
        SELF self = (SELF)this;
        return self;
    }
    
    /**
     * 获取交易组
     * @return TradeRoleGroup
     */
    public CommodityLicenseGroup getLicenseGroup() {
        return CommodityLicenseGroup.of(this.currentParticipant,licenses);
    }
    
    /**
     * 
     * @param currentParticipant
     * @param licenses
     */
    public static TradeProxy<?> of (String name,Map<String,CommodityLicense<Commodity,Commodity>> licenses) {
        return new TradeProxy<>(name,licenses);
    }
    
    public String currentParticipant;
    private Map<String,CommodityLicense<Commodity,Commodity>> licenses;
}
